package com.bibimaya.auto.mapper.dao.utils;


import com.bibimaya.auto.mapper.dao.constant.Const;

import java.util.Date;

/**
 * WhereSqlUtil
 * create by lijianwei
 */
public class WhereSqlUtil {

    public static final String START = "Start";

    public static final String END = "End";

    public static final String LIST = "List";

    public static final String LIKE = "Like";

    public static final String PREFIXLIKE = "PrefixLike";

    public static final String SUFFIXLIKE = "SuffixLike";



    public static String whereSql(EntityMap entityMap, String tab){
        return whereSql(entityMap, tab, null);
    }

    /**
     * only filed equals
     * @param entityMap
     * @param tab
     * @param whereSqlAppend
     * @return
     */
    public static String whereSql(EntityMap entityMap, String tab, String whereSqlAppend){
        StringBuffer whereSql = new StringBuffer();
        String tabNew = tab == null ? Const.STR_EMPTY : tab;
        whereSql.append(tabNew).append("<where>");
        String tabInner = tabNew + Const.TAB;
        whereSql.append(Const.NEW_LINE);
        for (int i = 0; i < entityMap.getFields().size(); i++) {
            FieldMap fm = entityMap.getFields().get(i);
            whereSql.append(equalsWhere(fm, tabInner));
            whereSql.append(whereSqlWithOv(fm, tabInner));
        }
        if(whereSqlAppend != null && !whereSqlAppend.isEmpty()) {
            whereSql.append(whereSqlAppend);
        }
        whereSql.append(tabNew).append("</where>");
        whereSql.append(Const.NEW_LINE);
        return whereSql.toString();
    }

    /**
     * where only use ov
     * @param entityMap
     * @param tab
     * @param whereSqlAppend
     * @return
     */
    public static String whereSqlWithOv(EntityMap entityMap, String tab, String whereSqlAppend){
        StringBuffer whereSql = new StringBuffer();
        String tabNew = tab == null ? Const.STR_EMPTY : tab;
        whereSql.append(tabNew).append("<where>");
        String tabInner = tabNew + Const.TAB;
        whereSql.append(Const.NEW_LINE);
        for (int i = 0; i < entityMap.getFields().size(); i++) {
            FieldMap fm = entityMap.getFields().get(i);
            whereSql.append(whereSqlWithOv(fm, tabInner));
        }
        whereSql.append(whereSqlAppend);
        whereSql.append(tabNew).append("</where>");
        whereSql.append(Const.NEW_LINE);
        return whereSql.toString();
    }

    public static String whereSqlWithOv(FieldMap fm, String tab){

        StringBuffer innerSql = new StringBuffer();
        String tabInner = tab + Const.TAB;
        if(Number.class.isAssignableFrom(fm.getType())){
            innerSql.append(inWhere(fm, tabInner));
            innerSql.append(betweenWhere(fm, tabInner));
        }else if(String.class.equals(fm.getType())){
            //未避免生成的无用sql过多，这里暂时不启用这些
//            sql.append(inWhere(fm, tabInner));
//            sql.append(likeWhere(fm, tabInner));
//            sql.append(prefixLikeWhere(fm, tabInner));
//            sql.append(suffixLikeWhere(fm, tabInner));
        }else if(Date.class.equals(fm.getType())){
            innerSql.append(betweenWhere(fm,tabInner));
        }
        if(innerSql == null || innerSql.length() == 0){
            return innerSql.toString();
        }
        StringBuffer sql = new StringBuffer();
        sql.append(tab).append("<if test='ov != null'>");
        sql.append(Const.NEW_LINE);
        sql.append(innerSql);
        sql.append(tab).append("</if>");
        sql.append(Const.NEW_LINE);
        return sql.toString();
    }

    public static String equalsWhere(FieldMap fm, String tab){
        if(fm == null){
            return Const.STR_EMPTY;
        }
        String tabTmp = tab == null ? Const.STR_EMPTY :tab;
        StringBuffer sql = new StringBuffer();
        sql.append(tabTmp);
        sql.append("<if test='"+fm.getField()+" != null'>");
        sql.append(Const.NEW_LINE);
        sql.append(tabTmp).append(Const.TAB).append("and `"+fm.getColumn()+"` = #{"+fm.getField()+"} ");
        sql.append(Const.NEW_LINE);
        sql.append(tabTmp).append("</if>");
        sql.append(Const.NEW_LINE);
        return sql.toString();
    }

    public static String betweenWhere(FieldMap fm, String tab){
        if(fm == null){
            return Const.STR_EMPTY;
        }
        String tabTmp = tab == null ? Const.STR_EMPTY : tab;
        StringBuffer sql = new StringBuffer();
        String paramStartName = "ov."+ fm.getField() +START;
        sql.append(tabTmp).append("<if test='"+paramStartName+" != null'>");
        sql.append(Const.NEW_LINE);
        sql.append(tabTmp).append(Const.TAB);
        sql.append("and ").append("`"+fm.getColumn()+"`").append(" >= #{").append(paramStartName).append("}");
        sql.append(Const.NEW_LINE);
        sql.append(tabTmp).append("</if>");
        sql.append(tabTmp).append(Const.NEW_LINE);

        String paramEndName = "ov."+ fm.getField() +END;
        sql.append(tabTmp).append("<if test='"+paramEndName+" != null'>");
        sql.append(Const.NEW_LINE);
        sql.append(tabTmp).append(Const.TAB);
        sql.append("and ").append("`"+fm.getColumn()+"`").append(" &lt;= #{").append(paramEndName).append("}");
        sql.append(Const.NEW_LINE);
        sql.append(tabTmp).append("</if>");
        sql.append(Const.NEW_LINE);
        return sql.toString();
    }

    public static String inWhere(FieldMap fm, String tab){
        if(fm == null){
            return Const.STR_EMPTY;
        }
        String tabTmp = tab == null ? Const.STR_EMPTY :tab;
        StringBuffer sql = new StringBuffer();
        sql.append(tabTmp);
        String paramName = "ov." + fm.getField() + LIST;
        sql.append("<if test='"+ paramName +" != null and " + paramName + ".size() > 0'>");
        sql.append(Const.NEW_LINE);
        sql.append(tabTmp).append(Const.TAB).append("and `"+fm.getColumn()+"` in ");
        sql.append(Const.NEW_LINE);
        sql.append(tabTmp).append(Const.TAB);
        sql.append("<foreach item='item' collection='"+ paramName +"' open='(' separator=',' close=')'>");
        sql.append(Const.NEW_LINE);
        sql.append(tabTmp).append(Const.TAB).append(Const.TAB).append("#{item}");
        sql.append(Const.NEW_LINE);
        sql.append(tabTmp).append(Const.TAB).append("</foreach>");
        sql.append(Const.NEW_LINE);
        sql.append(tabTmp).append("</if>");
        sql.append(Const.NEW_LINE);
        return sql.toString();
    }

    public static String inFieldWhere(FieldMap fm, String tab){
        if(fm == null){
            return Const.STR_EMPTY;
        }
        String tabTmp = tab == null ? Const.STR_EMPTY :tab;
        StringBuffer sql = new StringBuffer();
        sql.append(tabTmp);
        sql.append("<if test='list != null and list.size() > 0'>");
        sql.append(Const.NEW_LINE);
        sql.append(tabTmp).append(Const.TAB).append("and `"+fm.getColumn()+"` in ");
        sql.append(Const.NEW_LINE);
        sql.append(tabTmp).append(Const.TAB);
        sql.append("<foreach item='item' collection='list' open='(' separator=',' close=')'>");
        sql.append(Const.NEW_LINE);
        sql.append(tabTmp).append(Const.TAB).append(Const.TAB).append("#{item."+fm.getField()+"}");
        sql.append(Const.NEW_LINE);
        sql.append(tabTmp).append(Const.TAB).append("</foreach>");
        sql.append(Const.NEW_LINE);
        sql.append(tabTmp).append("</if>");
        sql.append(Const.NEW_LINE);
        return sql.toString();
    }

    public static String likeWhere(FieldMap fm, String tab){
        if(fm == null){
            return Const.STR_EMPTY;
        }
        String tabTmp = tab == null ? Const.STR_EMPTY :tab;
        StringBuffer sql = new StringBuffer();
        sql.append(tabTmp);
        String paramName = "ov."+ fm.getField() +LIKE;
        sql.append("<if test='"+ paramName +" != null and "+ paramName +" != \"\"'>");
        sql.append(Const.NEW_LINE);
        sql.append(tabTmp).append(Const.TAB);
        sql.append("and `"+fm.getColumn()+"` like CONCAT('%',#{"+ paramName +"}, '%')");
        sql.append(Const.NEW_LINE);
        sql.append(tabTmp).append("</if>");
        sql.append(Const.NEW_LINE);
        return sql.toString();
    }

    public static String prefixLikeWhere(FieldMap fm, String tab){
        if(fm == null){
            return Const.STR_EMPTY;
        }
        String tabTmp = tab == null ? Const.STR_EMPTY :tab;
        StringBuffer sql = new StringBuffer();
        sql.append(tabTmp);
        String paramName = "ov."+ fm.getField() +PREFIXLIKE;
        sql.append("<if test='"+ paramName +" != null and "+ paramName +" != \"\"'>");
        sql.append(Const.NEW_LINE);
        sql.append(tabTmp).append(Const.TAB);
        sql.append("and `"+fm.getColumn()+"` like CONCAT('%', #{"+ paramName +"})");
        sql.append(Const.NEW_LINE);
        sql.append(tabTmp).append("</if>");
        sql.append(Const.NEW_LINE);
        return sql.toString();
    }

    public static String suffixLikeWhere(FieldMap fm, String tab){
        if(fm == null){
            return Const.STR_EMPTY;
        }
        String tabTmp = tab == null ? Const.STR_EMPTY :tab;
        StringBuffer sql = new StringBuffer();
        sql.append(tabTmp);
        String paramName = "ov." + fm.getField() + SUFFIXLIKE;
        sql.append("<if test='"+ paramName +" != null and "+ paramName +" != \"\"'>");
        sql.append(Const.NEW_LINE);
        sql.append(tabTmp).append(Const.TAB);
        sql.append("and `"+fm.getColumn()+"` like CONCAT(#{" + paramName + "},'%')");
        sql.append(Const.NEW_LINE);
        sql.append(tabTmp).append("</if>");
        sql.append(Const.NEW_LINE);
        return sql.toString();
    }

}
